home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.02 Feb 90 / Bit Mapper Source / BTMP2 / BitMapper_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-19  |  12.2 KB  |  469 lines  |  [TEXT/KAHL]

  1. /* ======================================= *
  2.     file:    BitMapper_main.c
  3.     version:    2
  4.     date:    11.13.89
  5.  * --------------------------------------- *
  6.     Copyright © 1989, Michael Ogawa and
  7.     MacTutor — All Rights Reserved.
  8.  * ======================================= */
  9.  
  10. /* #include <MacHeaders> */
  11. #include "BitMapper.h"
  12.  
  13. #ifdef applec
  14. #    include <Desk.h>
  15. #    include <Scrap.h>
  16. #    include <Packages.h>
  17.     typedef char    SignedByte;
  18. #endif applec
  19.  
  20.  
  21. /* Code resource entry point (MPW) ======= */
  22.  
  23. #ifdef applec
  24. pascal void BitMapper(short selector,
  25.     MenuDataPtr toolInfo, long *refCon,
  26.     short *returnCode)
  27. /*    Code resource entry point for a
  28. SuperPaint transformation command plug-in
  29. tool built in MPW C.  This avoids having to
  30. forward reference all the internal
  31. routines. */
  32. /*    m_o 06.23.89 */
  33. {
  34.     main(selector, toolInfo, refCon,
  35.         returnCode);
  36. }
  37. #endif applec
  38.  
  39.  
  40. /* private functions ===================== */
  41.  
  42. static short OpenOutput(
  43.     TBitMapperPtr pMyInfo)
  44. /*    Prepares the appropriate output method.
  45. PMyInfo is a pointer to a BitMapper record
  46. containing information about the currently
  47. executing command.
  48.     This version of OpenOutput() simply
  49. prepares output to the desk scrap.  The
  50. clipboard is cleared, and as a workaround for
  51. MultiFinder’s selective updating of other
  52. partitions’ ScrapCount low-memory variable,
  53. SystemEdit() is called with the copy message.
  54. (See “Macintosh Technical Note #180:
  55. MultiFinder Miscellanea” for details.)
  56.     If no error occured then the result code
  57. noErr is returned as the function return
  58. value; otherwise an appropriate Operating
  59. System result code is returned as the
  60. function return value. */
  61. /*    m_o 11.13.89 */
  62. {
  63. #    pragma unused(pMyInfo)
  64.  
  65.     /* MultiFinder work-around: notify
  66.        System of copy operation… */
  67.     (void)SystemEdit(3);
  68.     /* clear the desk scrap… */
  69.     return(ZeroScrap());
  70. }
  71.  
  72.  
  73. static short DoOutput(Handle hData,
  74.     ResType rType, TBitMapperPtr pMyInfo)
  75. /*    Outputs the data in the relocatable
  76. block specified by the handle hData.  The
  77. data output format is specified by rType.
  78. PMyInfo is a pointer to a BitMapper record
  79. containing information about currently
  80. executing command.
  81.     This version of DoOutput() simply sends
  82. the data to the clipboard using the Toolbox
  83. routine PutScrap(), specifying rType as the
  84. Desk scrap data type.  Note that it does not
  85. call ZeroScrap(), so the output is added to
  86. the current scrap content as an additional
  87. type.  This is not good if the scrap already
  88. contains a resource of the specified type.
  89. Therefore, ZeroScrap() should be called once
  90. before outputting any data to the scrap.
  91.     If no error occured then the result code
  92. noErr is returned as the function return
  93. value; otherwise an appropriate Operating
  94. System result code is returned as the
  95. function return value. */
  96. /*    m_o 11.13.89 */
  97. {
  98. #    pragma unused(pMyInfo)
  99.     SignedByte savedMPFlags;
  100.     short result;
  101.  
  102.     /* get master pointer flags and lock down… */
  103.     savedMPFlags = HGetState(hData);
  104.     MoveHHi(hData);
  105.     HLock(hData);
  106.  
  107.     result = PutScrap(GetHandleSize(hData),
  108.         rType, *hData);
  109.  
  110.     /* restore master pointer state… */
  111.     HSetState(hData, savedMPFlags);
  112.  
  113.     return(result);
  114. }
  115.  
  116.  
  117. static void CopyBits2Buffer(
  118.     const BitMap *pSrcBMap,
  119.     const Rect *pSrcRect, Ptr pBuffer,
  120.     short bufferRowBytes, short mode)
  121. /*    Transfers a bit image specified by the
  122. bit map *pSrcMap to the image buffer
  123. pBuffer[].  The image buffer must begin on an
  124. even address.  The width, in bytes, of the
  125. destination buffer is specified by
  126. bufferRowBytes, which must also be even.
  127.     The bits enclosed by the source
  128. rectangle *pSrcRect are transferred to a
  129. similar sized rectangle in the destination
  130. image.  The destination rectangle is the same
  131. size as the source rectangle and is aligned
  132. at the top left corner of the destination bit
  133. image.  The destination image buffer must be
  134. big enough to accomodate the entire image
  135. being transferred.  The transfer mode is
  136. specified by the mode parameter. */
  137. /*    m_o 06.22.89 */
  138. {
  139.     BitMap dstBMap;
  140.  
  141.     dstBMap.baseAddr = pBuffer;
  142.     dstBMap.rowBytes = bufferRowBytes;
  143.     dstBMap.bounds = *pSrcRect;
  144.     CopyBits(pSrcBMap, &dstBMap, pSrcRect,
  145.         pSrcRect, mode, NULL);
  146. }
  147.  
  148.  
  149. static short PutPICT(TBitMapperPtr pMyInfo)
  150. /*    Makes a picture that is a copy of the
  151. selection area our command is working with,
  152. then outputs the picture.  PMyInfo is a
  153. pointer to a BitMapper record containing
  154. information about currently executing
  155. command.  This includes a grafPtr to the
  156. document port (which is also the current
  157. port).
  158.     Before calling us, SuperPaint has
  159. already set the port’s portRect to be
  160. equivalent to the selection bounding
  161. rectangle in a coordinate system local to the
  162. selection.  That is, portRect.topLeft is
  163. (0,0), portRect.bottom is equal to the height
  164. of the selection area, and portRect.right is
  165. equal to the width of the selection area.
  166.     If no error occured then the result code
  167. noErr is returned as the function return
  168. value; otherwise an appropriate Operating
  169. System result code is returned as the
  170. function return value. */
  171. /*    m_o 09.13.89 */
  172. {
  173.     short result;
  174.     PicHandle hMyPic;
  175.  
  176.     if (hMyPic = OpenPicture(
  177.         &pMyInfo->drawGptr->portRect)) {
  178.         /* copy selection… */
  179.         CopyBits(
  180.             &pMyInfo->drawGptr->portBits,
  181.             &pMyInfo->drawGptr->portBits,
  182.             &pMyInfo->drawGptr->portRect,
  183.             &pMyInfo->drawGptr->portRect,
  184.             srcCopy, NULL);
  185.         ClosePicture();
  186.         result = DoOutput((Handle)hMyPic,
  187.             'PICT', pMyInfo);
  188.         KillPicture(hMyPic);
  189.     } else
  190.         result = MemError();
  191.     return(result);
  192. }
  193.  
  194.  
  195. static short PutBTMP(TBitMapperPtr pMyInfo)
  196. /*    Makes a 'BTMP' resource from the
  197. selection area our command is working with,
  198. then outputs the resource.  PMyInfo is a
  199. pointer to a BitMapper record containing
  200. information about the currently executing
  201. command.  This includes a grafPtr to the
  202. document port (which is also the current
  203. port).
  204.     Before calling us, SuperPaint has
  205. already set the port’s portRect to be
  206. equivalent to the selection bounding
  207. rectangle in a coordinate system local to the
  208. selection.  That is, portRect.topLeft is
  209. (0,0), portRect.bottom is equal to the height
  210. of the selection area, and portRect.right is
  211. equal to the width of the selection area.
  212.     If no error occured then the result code
  213. noErr is returned as the function return
  214. value; otherwise an appropriate Operating
  215. System result code is returned as the
  216. function return value. */
  217. /*    m_o 09.17.89 */
  218. {
  219.     long sz;
  220.     short result;
  221.     BitMap myMap;
  222.     TBTMPPkHndl hMyBTMP;
  223.  
  224.     /* set up BitMap: init baseAddr… */
  225.     myMap.baseAddr = NULL;
  226.     /* get bounds rectangle… */
  227.     myMap.bounds =
  228.         pMyInfo->drawGptr->portRect;
  229.     /* calc rowBytes… */
  230.     myMap.rowBytes =
  231.         BITS2ROWBYTES(WIDTH(myMap.bounds));
  232.     /* calc size of 'BTMP' resource… */
  233.     sz = sizeof(TBTMP) +
  234.         myMap.bounds.bottom *
  235.         myMap.rowBytes;
  236.  
  237.     /* get ‘clean’ memory for new
  238.        'BTMP' resource… */
  239.     if (!(hMyBTMP =
  240.         (TBTMPPkHndl)NewHandleClear(sz)))
  241.         return(MemError());
  242.  
  243.     /* copy BitMap… */
  244.     (**hMyBTMP).map = myMap;
  245.  
  246.     /* copy bit image… */
  247.     MoveHHi((Handle)hMyBTMP);
  248.     HLock((Handle)hMyBTMP);
  249.     CopyBits2Buffer(
  250.         &pMyInfo->drawGptr->portBits,
  251.         &myMap.bounds,
  252.         (Ptr)&(**hMyBTMP).image,
  253.         myMap.rowBytes, srcCopy);
  254.     HUnlock((Handle)hMyBTMP);
  255.  
  256.     /* ship it! */
  257.     result = DoOutput((Handle)hMyBTMP,
  258.         'BTMP', pMyInfo);
  259.  
  260.     /* clean up and leave… */
  261.     DisposHandle((Handle)hMyBTMP);
  262.     return(result);
  263. }
  264.  
  265.  
  266. static short PutBTMN(TBitMapperPtr pMyInfo)
  267. /*    Makes a 'BTM#' resource from the
  268. selection area our command is working with,
  269. then outputs the resource.  PMyInfo is a
  270. pointer to a BitMapper record containing
  271. information about the currently executing
  272. command.  This includes a grafPtr to the
  273. document port (which is also the current
  274. port).
  275.     Before calling us, SuperPaint has
  276. already set the port’s portRect to be
  277. equivalent to the selection bounding
  278. rectangle in a coordinate system local to the
  279. selection.  That is, portRect.topLeft is
  280. (0,0), portRect.bottom is equal to the height
  281. of the selection area, and portRect.right is
  282. equal to the width of the selection area.
  283.     If no error occured then the result code
  284. noErr is returned as the function return
  285. value; otherwise an appropriate Operating
  286. System result code is returned as the
  287. function return value. */
  288. /*    m_o 11.17.89 */
  289. {
  290.     long sz;
  291.     short result;
  292.     BitMap myMap;
  293.     TBTMNHndl hMyBTMN;
  294.     TBTMNEntryPtr pMyBTMNEntry;
  295.  
  296.     /* set up BitMap: init baseAddr… */
  297.     myMap.baseAddr = NULL;
  298.     /* get bounds rectangle… */
  299.     myMap.bounds =
  300.         pMyInfo->drawGptr->portRect;
  301.     /* calc rowBytes… */
  302.     myMap.rowBytes =
  303.         BITS2ROWBYTES(WIDTH(myMap.bounds));
  304.     /* calc size of 'BTMP' resource… */
  305.     sz = sizeof(TBTMP) +
  306.         myMap.bounds.bottom *
  307.         myMap.rowBytes;
  308.  
  309.     /* get ‘clean’ memory for new
  310.        'BTM#' resource… */
  311.     if (!(hMyBTMN =
  312.         (TBTMNHndl)NewHandleClear(sz +
  313.         sizeof((**hMyBTMN).count) +
  314.         sizeof((**hMyBTMN).
  315.         theBTMNEntries[0].szEntry))))
  316.         return(MemError());
  317.  
  318.     /* number of BTMP entries… */
  319.     (**hMyBTMN).count = 1;
  320.     /* lock, get pointer to entry… */
  321.     MoveHHi((Handle)hMyBTMN);
  322.     HLock((Handle)hMyBTMN);
  323.     pMyBTMNEntry =
  324.         (**hMyBTMN).theBTMNEntries;
  325.     /* size of the BTM# entry… */
  326.     pMyBTMNEntry->szEntry =
  327.         sizeof(pMyBTMNEntry->szEntry) + sz;
  328.     /* copy BitMap… */
  329.     pMyBTMNEntry->theBTMP.map = myMap;
  330.     /* copy bit image… */
  331.     CopyBits2Buffer(
  332.         &pMyInfo->drawGptr->portBits,
  333.         &myMap.bounds,
  334.         (Ptr)pMyBTMNEntry->theBTMP.image,
  335.         myMap.rowBytes, srcCopy);
  336.     HUnlock((Handle)hMyBTMN);
  337.  
  338.     /* ship it! */
  339.     result = DoOutput((Handle)hMyBTMN,
  340.         'BTM#', pMyInfo);
  341.  
  342.     /* clean up and leave… */
  343.     DisposHandle((Handle)hMyBTMN);
  344.     return(result);
  345. }
  346.  
  347.  
  348. static short DoIt(TBitMapperPtr pMyInfo)
  349. /*    Makes a 'BTMP' or 'BTM#' resource and a
  350. picture from the selection area our command
  351. is working with, then outputs the resources.
  352. PMyInfo is a pointer to a BitMapper record
  353. containing information about currently
  354. executing command.  All its fields should be
  355. filled in on entry, except the drawGptr field
  356. which this routine fills in.  (The drawGptr
  357. field is a grafPtr to the document port,
  358. which is also the current port.)
  359.     The menuItem field of the menu command
  360. data record specified by the BitMapper record
  361. specifies whether to create a 'BTMP' or 'BTM#'
  362. resource.
  363.     If no error occured then the result code
  364. noErr is returned as the function return
  365. value; otherwise an appropriate Operating
  366. System result code is returned as the
  367. function return value. */
  368. /*    m_o 11.17.89 */
  369. {
  370.     short result;
  371.  
  372.     GetPort(&pMyInfo->drawGptr);
  373.     if ((result = OpenOutput(pMyInfo)) ==
  374.         noErr) {
  375.         short result2;
  376.  
  377.         result =
  378.             (pMyInfo->pToolInfo->menuItem
  379.             == kMITEM_BTMP) ?
  380.             PutBTMP(pMyInfo) :
  381.             PutBTMN(pMyInfo);
  382.         if ((result2 = PutPICT(pMyInfo)) !=
  383.             noErr && result == noErr)
  384.             result = result2;
  385.     }
  386.     return(result);
  387. }
  388.  
  389.  
  390. static void AlertErr(short err,
  391.     short baseID)
  392. /*    Puts up an alert telling the user an
  393. error occured.  Err is the result code of
  394. the error.  This is converted to a string
  395. and substituted for param text ^0 in the
  396. alert.
  397.     BaseID is the resource ID of the first
  398. (numerically lowest) resource in our plug-in
  399. tool.  Because resource IDs may be
  400. reassigned, we calculate our alert’s current
  401. resource ID based on this. */
  402. /*    m_o 09.30.89 */
  403. {
  404.     Str255 s;
  405.     unsigned char str0 = '\0';
  406.  
  407.     /* Convert error ID to string format,
  408.        put into param text ^0.  Note usage
  409.        of “str0” because we can’t have any
  410.        globals.  Not even empty strings! */
  411.     NumToString(err, s);
  412.     ParamText(s, &str0, &str0, &str0);
  413.     /* The following line would be illegal!!
  414.        ParamText(s, "", "", ""); */
  415.  
  416.     CenterWindow('ALRT',
  417.         baseID + kALRT_Err);
  418.     /* make sure cursor is arrow… */
  419.     InitCursor();
  420.  
  421.     NoteAlert(baseID + kALRT_Err, NULL);
  422. }
  423.  
  424. /* entry points ========================== */
  425.  
  426. pascal void main(short selector,
  427.     MenuDataPtr toolInfo, long *refCon,
  428.     short *returnCode)
  429. /*    Entry point and command dispatcher for
  430. the BitMapper plug-in command tool.  Selector
  431. is a call type code as defined by Silicon
  432. Beach Software in the Menu Command Interface
  433. section of their plug-in documentation
  434. “Developing Plug-In Modules for SuperPaint”.
  435. */
  436. /*    m_o 08.29.89 */
  437. {
  438.     TBitMapperRec myInfo;
  439.  
  440.     switch (selector) {
  441.     case menuAbout:
  442.         /* tell SuperPaint we have TEXT
  443.            resource for About Box info… */
  444.         *returnCode = textAbout;
  445.         break;
  446.     case menuOptions:
  447.         /* tell SuperPaint we don’t need
  448.            a scratch buffer… */
  449.         ((MenuOptionsPtr)toolInfo)->
  450.             usesScratch = false;
  451.         *returnCode = noErr;
  452.         break;
  453.     case menuSelected:
  454.         /* setup private data record
  455.            and do it!… */
  456.         myInfo.pToolInfo = toolInfo;
  457.         myInfo.pRefCon = refCon;
  458.         *returnCode = DoIt(&myInfo);
  459.         break;
  460.     }
  461.  
  462.     /* alert user on errors… */
  463.     if (*returnCode != noErr &&
  464.         selector != menuAbout)
  465.         AlertErr(*returnCode,
  466.             toolInfo->toolID);
  467.     return;
  468. }
  469.